﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel;

namespace EncoderTester
{
    public class EncoderConfiguration
    {
        public BasicOptions Basic { get; set; }
        public VideoOptions Video { get; set; }
        public AudioOptions Audio { get; set; }
        public AdvancedOptions Advanced { get; set; }
        public MotionEstimationOptions MotionEstimation { get; set; }
        public FilterOptions Filters { get; set; }
        public QuantizationOptions Quantization { get; set; }

        public EncoderConfiguration()
        {
            Basic = new BasicOptions();
            Video = new VideoOptions();
            Audio = new AudioOptions();
            Advanced = new AdvancedOptions();
            MotionEstimation = new MotionEstimationOptions();
            Filters = new FilterOptions();
            Quantization = new QuantizationOptions();
        }

        public class BasicOptions : INotifyPropertyChanged
        {
            private string m_InputFile;
            public string InputFile
            {
                get { return m_InputFile; }
                set
                {
                    m_InputFile = value;
                    OnPropertyChanged("InputFile");
                }
            }

            private string m_OutputFile;
            public string OutputFile
            {
                get { return m_OutputFile; }
                set
                {
                    m_OutputFile = value;
                    OnPropertyChanged("OutputFile");
                }
            }
            public uint Profile { get; set; }
            public uint RateControlMode { get; set; }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

            #endregion
        }

        public class VideoOptions
        {
            public uint BitRate { get; set; }
            public uint ComplexityLevel { get; set; }
            public uint QP { get; set; }
            public double FrameRate { get; set; }
            public bool InterlacedSource { get; set; }
            public uint MaxKeyFrameDistance { get; set; }
            public uint MaximumHeight { get; set; }
            public uint MaximumWidth { get; set; }
            public uint NumBFrames { get; set; }
            public uint PeakBitRate { get; set; }
        }

        public class AudioOptions : INotifyPropertyChanged
        {
            private string m_AudioProfile;
            public string AudioProfile
            {
                get { return m_AudioProfile; }
                set
                {
                    m_AudioProfile = value;
                    OnPropertyChanged("AudioProfile");
                }
            }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

            #endregion
        }

        public class AdvancedOptions
        {
            public bool AdaptiveGOP { get; set; }
            public uint BFrameDeltaQP { get; set; }
            public bool ClosedEntryPoint { get; set; }
            public uint KeyPopReduction { get; set; }
            public bool LetterBoxPresent { get; set; }
            public bool LookAhead { get; set; }
            public uint NumThreads { get; set; }
            public uint OutputMode { get; set; }
            public uint VideoType { get; set; }
        }

        public class MotionEstimationOptions
        {
            public uint DeltaMVRangeIndex { get; set; }
            public uint MotionSearchLevel { get; set; }
            public uint MotionSearchMethod { get; set; }
            public uint MacroblockModeCost { get; set; }
            public uint MotionVectorCost { get; set; }
            public uint MotionVectorRange { get; set; }
        }

        public class FilterOptions
        {
            public bool UseInLoop { get; set; }
            public bool UseMedian { get; set; }
            public bool UseDenoise { get; set; }
            public bool UseOverlapSmoothing { get; set; }
            public bool UseNoiseEdgeRemoval { get; set; }
        }

        public class QuantizationOptions
        {
            public uint AdaptiveQuantization { get; set; }
            public uint DifferentialQuantization { get; set; }
            public uint PFrameStrength { get; set; }
            public uint BFrameStrength { get; set; }
        }

        public static EncoderConfiguration Load(string filename)
        {
            EncoderConfiguration config = null;
            XmlSerializer xmlSer = new XmlSerializer(typeof(EncoderConfiguration));
            using (FileStream fs = File.OpenRead(filename))
            {
                config = (EncoderConfiguration)xmlSer.Deserialize(fs);
            }
            return config;
        }

        public void Save(string filename)
        {
            XmlSerializer xmlSer = new XmlSerializer(typeof(EncoderConfiguration));
            using (StreamWriter sw = new StreamWriter(filename))
            {
                xmlSer.Serialize(sw, this);
            }
        }
    }
}
